﻿using System;
using System.IO;
using System.Text;

namespace Microsoft.Azure.E2E.Common.Net
{
    /// <summary>
    /// A part of a <see cref="MultipartMessage"/>
    /// </summary>
    public abstract class MessagePart: IDisposable
    {
        /// <summary>
        /// Gets a <see cref="Stream"/> representation of a <see cref="String"/>
        /// </summary>
        /// <param name="value">The string to get a stream for</param>
        /// <returns>A stream representing the string</returns>
        protected static Stream StreamFromString(string value)
        {
            var bytes = Encoding.UTF8.GetBytes(value);
            return new MemoryStream(bytes);
        }

        /// <summary>
        /// Gets the name of the part
        /// </summary>
        public abstract string Name { get; }

        /// <summary>
        /// Gets the content disposition header value for the part
        /// </summary>
        public abstract string ContentDisposition { get; }

        /// <summary>
        /// Gets a stream representing the value contained in the part
        /// </summary>
        /// <returns>A stream representing the value contained in the part</returns>
        protected abstract Stream GetDataStream();

        /// <summary>
        /// Gets whatever value must follow the name attribute on the part separator, return null if nothing is required
        /// </summary>
        protected virtual string NameTail { get { return null; } }

        /// <summary>
        /// Gets a stream representing the whole part, including the boundary
        /// </summary>
        /// <param name="message">The message the part will be a part of</param>
        /// <returns>A stream representing the whole part, including the boundary</returns>
        public virtual Stream GetStream(MultipartMessage message)
        {
            var multiStream = new MultiStream();
            var head = StreamFromString(string.Format("--{0}{1}Content-Disposition: {3}; name=\"{2}\"{4}{5}{1}{1}", message.Boundary, "\r\n", Name, ContentDisposition, !string.IsNullOrEmpty(NameTail) ? ";":"", NameTail));
            var body = GetDataStream();
            var tail = StreamFromString("\r\n");
            return multiStream
                .AddStream(head)
                .AddStream(body)
                .AddStream(tail);
        }

        /// <summary>
        /// Frees any resources used by the part
        /// </summary>
        public virtual void Dispose()
        {
        }
    }
}